#include <my_header.h>
// 客户端设置非阻塞的recv 一次性读完全部数据不阻塞
/* Usage: ./10_client_epoll_非阻塞的recv */
int main(void){                      
    // 服务端 ip和端口
    char *ip = "192.168.229.128";
    char *port = "8080";

    // 创建socket对象
    int sofd = socket(AF_INET, SOCK_STREAM, 0);
    ERROR_CHECK(sofd, -1, "socket");

    // 创建struct sockaddr 类型
    struct sockaddr_in client_addr;
    client_addr.sin_family = AF_INET;
    client_addr.sin_port = htons(atoi(port));
    client_addr.sin_addr.s_addr = inet_addr(ip);

    // 建立连接
    int res_conn = connect(sofd, (struct sockaddr *)&client_addr, sizeof(client_addr));
    ERROR_CHECK(res_conn, -1, "connect");
    // 创建epoll对象
    int epoll_fd = epoll_create(1);
    ERROR_CHECK(epoll_fd, -1, "epoll_create");

    // 放入监听
    struct epoll_event event;
    event.events = EPOLLIN;
    event.data.fd = STDIN_FILENO;
    int res_epoctl = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, STDIN_FILENO, &event);
    ERROR_CHECK(res_epoctl, -1, "epoll_ctl");

    event.events = EPOLLIN | EPOLLET;
    event.data.fd = sofd;
    int res_epoctl1 = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sofd, &event);
    ERROR_CHECK(res_epoctl1, -1, "epoll_ctl");

    int flag = 0;
    while(1)
    {
        // 开始监听
        // epoll_wait:是一个阻塞函数

        struct epoll_event list[10];
        memset(list, 0, sizeof(list));
        int epoll_num = epoll_wait(epoll_fd, list, 10, -1);
        ERROR_CHECK(epoll_num, -1, "epoll_wait");

        // 至少所监听的文件描述符有一个就绪
        // 处理就绪问题：遍历就绪集合
        for(int i=0; i<epoll_num; i++)
        {
            int fd = list[i].data.fd;

            if(fd == sofd)
            {
                // 需求: 现在客户端对服务端发过来的数据的socket对象, 使用边缘触发模式
                //      每次只读了10字节数据
                // 现在: 我想它既使用边缘触发, 又希望一次把数据读完, 
                // 说明对端发送信息
                while(1){


                    char buf[10] = { 0 };
                    int res_recv = recv(sofd, buf, sizeof(buf), MSG_DONTWAIT);
                    if(res_recv == -1)
                    {
                        //说明此时不可读：没数据
                        break;
                    }
                    if(res_recv == 0)
                    {
                        printf("server closed! \n");
                        flag =1;    // 需要从这里跳出
                        break;
                    }
                    printf("server message: %s\n", buf);
                }
            }else if(fd == STDIN_FILENO)
            {
                // 说明标准输入输入内容
                char buf[60] = { 0 };
                read(STDIN_FILENO, buf, sizeof(buf));
                send(sofd, buf, sizeof(buf), 0);
            }
        }
        // 在这里写判断
        if(flag != 0)
        {
            break;
        }
    }

    close(sofd);
    return 0;
}


